import sys
import socket
from PyQt5.QtWidgets import QApplication, QDialog, QVBoxLayout, QHBoxLayout, QPushButton, QLineEdit, QTextEdit, QLabel


class ChatClient(QDialog):
    def __init__(self):
        super().__init__()
        self.protocol = 'TCP'
        self.host = 'localhost'
        self.tcp_port = 1337
        self.udp_port = 1488
        self.socket = None

        self.protocol_label = QLabel(f'Protocol: {self.protocol}')
        self.host_label = QLabel(f'Host: {self.host}')
        self.port_label = QLabel(f'Port: {self.tcp_port}')
        self.message_edit = QLineEdit()
        self.chat_box = QTextEdit()
        self.send_button = QPushButton('Send')
        self.protocol_button = QPushButton('UDP')

        self.init_ui()

    def init_ui(self):
        layout = QVBoxLayout()
        top_layout = QHBoxLayout()
        top_layout.addWidget(self.protocol_label)
        top_layout.addWidget(self.host_label)
        top_layout.addWidget(self.port_label)
        layout.addLayout(top_layout)
        layout.addWidget(self.chat_box)
        bottom_layout = QHBoxLayout()
        bottom_layout.addWidget(self.message_edit)
        bottom_layout.addWidget(self.send_button)
        bottom_layout.addWidget(self.protocol_button)
        layout.addLayout(bottom_layout)
        self.setLayout(layout)
        self.setWindowTitle('Chat Client')
        self.send_button.clicked.connect(self.send_message)
        self.protocol_button.clicked.connect(self.switch_protocol)

    def send_message(self):
        message = self.message_edit.text().strip()
        if not message:
            return
        self.message_edit.setText('')
        self.chat_box.append(f'You: {message}')
        self.socket.sendall(message.encode())

    def switch_protocol(self):
        if self.protocol == 'TCP':
            self.protocol = 'UDP'
            self.port_label.setText(f'Port: {self.udp_port}')
            self.protocol_button.setText('TCP')
            self.socket.close()
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.socket.connect((self.host, self.udp_port))
        else:
            self.protocol = 'TCP'
            self.port_label.setText(f'Port: {self.tcp_port}')
            self.protocol_button.setText('UDP')
            self.socket.close()
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.connect((self.host, self.tcp_port))
        self.protocol_label.setText(f'Protocol: {self.protocol}')

    def run(self):
        if self.protocol == 'TCP':
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.connect((self.host, self.tcp_port))
        else:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            self.socket.connect((self.host, self.udp_port))

        while True:
            try:
                data = self.socket.recv(1024)
                if not data:
                    break
                message = data.decode().strip()
                self.chat_box.append(f'Server: {message}')
            except ConnectionResetError:
                break


if __name__ == '__main__':
    app = QApplication(sys.argv)
    client = ChatClient()
    client.show()
    client.run()
    sys.exit(app.exec_())
